package com.ruoyi.zsyh.controller.applet.agent;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.config.WxConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.wx.WXPayConfig;
import com.ruoyi.common.utils.wx.WXPayRequest;
import com.ruoyi.zsyh.controller.applet.user.WxUserController;
import com.ruoyi.zsyh.domain.*;
import com.ruoyi.zsyh.service.*;
import net.sf.json.JSONArray;
import org.aspectj.weaver.loadtime.Aj;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author yuexl
 */
@Controller
@RequestMapping("/applet/zsyh/wxpay/")
public class WxPaymentController {

    private Logger logger = LoggerFactory.getLogger(WxPaymentController.class);
    
    @Value("${wxconfig.appIdApplet}")
    private String appIdApplet;

    @Value("${wxconfig.appSecretApplet}")
    private String appSecretApplet;

    @Value("${wxconfig.partner}")
    private String partner;

    @Value("${wxconfig.partnerKey}")
    private String partnerKey;

    @Value("${wxconfig.notifyUrlFactoryRecharge}")
    private String notifyUrlFactoryRecharge;

    @Resource
    private WXPayConfig wxPayConfig;

    @Autowired
    private IZsyhPlatformFactoryService zsyhPlatformFactoryService;

    @Autowired
    private IZsyhFactoryBalanceDetailsService zsyhFactoryBalanceDetailsService;

    @Autowired
    private IZsyhAgentInfoService zsyhAgentInfoService;

    @Autowired
    private IZsyhAfterFactoryBalanceService zsyhAfterFactoryBalanceService;

    @Autowired
    private IZsyhAfterFactoryService zsyhAfterFactoryService;

    /**
     * 通用
     * 小程序获取openId 和 session_key
     * 用户授权获取手机号
     * https://api.weixin.qq.com/sns/jscode2session?appid=wxc2298573abab5690&secret=2668443994e3d65e93df98223533cf2d&js_code=021UM4ll220fM64hfrll27c8C62UM4lB&grant_type=authorization_code
     * @param response
     */
    @RequestMapping(value = "/getWxOpenId")
    @ResponseBody
    public AjaxResult appletsLoginPhone(HttpServletResponse response, HttpServletRequest request)throws Exception {
        String code = request.getParameter("code");
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appIdApplet+"&secret="+appSecretApplet+"&js_code="+code+"&grant_type=authorization_code";
        String json = UrlUtils.loadURL(url);
        Map<String, Object> wechatToken = JSON.parseObject(json, Map.class);
        return AjaxResult.success("操作成功", wechatToken);
    }


    /**
     * 会长授权获取头像昵称
     * @param response
     */
    @RequestMapping(value = "/saveAgentOpenId")
    @ResponseBody
    public AjaxResult saveAppletsInformation(HttpServletResponse response, HttpServletRequest request)throws Exception {
        String agentId = request.getParameter("agentId");
        String code = request.getParameter("code");
        String nickname = request.getParameter("nickname");//昵称
        String imgUrl = request.getParameter("imgUrl");//头像
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appIdApplet+"&secret="+appSecretApplet+"&js_code="+code+"&grant_type=authorization_code";
        logger.info("url====================================" + url);
        String json = UrlUtils.loadURL(url);
        logger.info("json====================================" + json);
        Map<String, Object> wechatToken = JSON.parseObject(json, Map.class);
        String session_key = String.valueOf(wechatToken.get("session_key"));
        String openid = String.valueOf(wechatToken.get("openid"));

        ZsyhAgentInfo user = zsyhAgentInfoService.selectZsyhAgentInfoById(agentId);
        if(user != null){
            ZsyhAgentInfo user1 = new ZsyhAgentInfo();
            user1.setId(agentId);
            user1.setAgentWximage(imgUrl);
            user1.setAgentNickname(nickname);
            user1.setAgentOpenid(openid);
            zsyhAgentInfoService.updateZsyhAgentInfoApplet(user1);
        }

        return AjaxResult.success("操作成功");
    }

    /**
     * 厂家余额充值
     * @param openId
     * @param response
     * @param request
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "/wxPayAppletsFactoryRecharge", method = RequestMethod.GET)
    public AjaxResult wxPayApplets(String factoryId, String openId, String totalfee, HttpServletResponse response, HttpServletRequest request) throws IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        //更改钱数
//        totalfee = "0.01";
        List<Map<String, Object>> commlist = new ArrayList<Map<String, Object>>();
        Map<String, Object> resultmap = new HashMap<String, Object>();
        //微信支付jsApi
        logger.info(openId);
        WxPayDto tpWxPay = new WxPayDto();
        tpWxPay.setOpenId(openId);
        tpWxPay.setBody("质保金余额充值");
        tpWxPay.setOrderId(IdWorker.getId());
        tpWxPay.setSpbillCreateIp("127.0.0.1");
        tpWxPay.setTotalFee(totalfee);
        tpWxPay.setAttach(factoryId);

        String returnresult = getPackageApplets(tpWxPay);
        logger.info(returnresult);
        String[] resultarray = returnresult.split(",");
        for (String item : resultarray) {
            String[] temp = item.split(":");
            logger.info("item" + item);
            logger.info("temp[0]" + temp[0] + "temp[1]" + temp[1]);
            temp[0] = temp[0].replaceAll("\"", "");
            temp[1] = temp[1].replaceAll("\"", "");
            resultmap.put(temp[0], temp[1]);
        }
        commlist.add(resultmap);
        JSONArray json = JSONArray.fromObject(commlist);
        response.reset();
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream out = response.getOutputStream();
        //out.print(callback + "(" + json + ")");

        logger.info("json**********" + json + "***************");
//        logger.info("callback"+callback+"*********************after");
        return AjaxResult.success(json);
    }


    /**
     * 小程序支付回调
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/repairNotifyFactoryRecharge", method = RequestMethod.POST)
    @ResponseBody
    public String notifyUrlApplets(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        WXPayRequest wxPayRequest = new WXPayRequest(this.wxPayConfig);
        Map<String, String> result = new HashMap<String, String>();
        Map<String, String> params = null;
        String returnxml = "";
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        //以字节流的形式读取request中的数据
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        params = WXPayUtil.xmlToMap(sb.toString());
        logger.info("1.notify-params>>>>>>>>>>>:" + params);

        String returnCode = params.get("return_code");
        logger.info("3.returnCode:" + returnCode);
        if (returnCode.equals("SUCCESS")) {
            //判断签名是否正确
            boolean flag = wxPayRequest.isResponseSignatureValid(params, partnerKey);
            logger.info("2.notify-flag:" + flag);
            if (flag) {
                //获取微信订单号
                String transactionId = params.get("transaction_id");
                //获取商户订单号
                String outTradeNo = params.get("out_trade_no");

                String total_fee = params.get("total_fee");//支付金额

                //附加信息原路返回 厂家id
                String attach = params.get("attach");
                logger.info("transactionId====================================" + transactionId);
                logger.info("outTradeNo====================================" + outTradeNo);
                logger.info("attach====================================" + attach);
                logger.info("total_fee====================================" + total_fee);
                outTradeNo = outTradeNo.substring(0, outTradeNo.length()-6);
                logger.info("outTradeNo====================================" + outTradeNo);
                //TODO 充值成功，保存余额明细，增加余额
                Double total = Double.valueOf(total_fee) * 0.01;
                BigDecimal totalFee = new BigDecimal(String.valueOf(total)).setScale(2, BigDecimal.ROUND_HALF_UP);
                ZsyhPlatformFactory factory = zsyhPlatformFactoryService.selectZsyhPlatformFactoryById(attach);
                BigDecimal balance = factory.getFactoryBalance();
                BigDecimal money = factory.getFactoryMoney();
                BigDecimal contractAmount = factory.getFactoryContractAmount();
                if(money.compareTo(contractAmount) > -1){
                    //保证金余额 大于等于 合同约定保证金金额
                    //本次充值所有金额添加到补助金余额
                    factory = new ZsyhPlatformFactory();
                    factory.setId(attach);
                    factory.setFactoryBalance(balance.add(totalFee).setScale(2, BigDecimal.ROUND_HALF_UP));
                    zsyhPlatformFactoryService.updateZsyhPlatformFactory(factory);


                    ZsyhFactoryBalanceDetails details = new ZsyhFactoryBalanceDetails();
                    details.setFactoryId(attach);
                    details.setFactoryMoney(totalFee);
                    details.setFactoryClassify("2");
                    details.setFactoryType("1");
                    details.setFactoryOrderNum(outTradeNo);
                    details.setFactoryTransactionId(transactionId);
                    details.setFactoryBalance(factory.getFactoryBalance());
                    zsyhFactoryBalanceDetailsService.insertZsyhFactoryBalanceDetails(details);



                }else{//保证金余额 小于 合同约定保证金金额
                    contractAmount = contractAmount.subtract(money);//合同约定保证金金额 减去 保证金余额 例如 合同约定500，余额300 差200
                    if(contractAmount.compareTo(totalFee) > -1){
                        //合同约定保证金金额 减去 保证金余额 大于等于 本次充值金额  例如 合同约定500，余额300 差200，本次充值100，那么本次充值金额全部加到保证金余额里
                        //本次充值所有金额添加到保证金余额里

                        factory = new ZsyhPlatformFactory();
                        factory.setId(attach);
                        factory.setFactoryMoney(money.add(totalFee).setScale(2, BigDecimal.ROUND_HALF_UP));
                        zsyhPlatformFactoryService.updateZsyhPlatformFactory(factory);

                        ZsyhFactoryBalanceDetails details = new ZsyhFactoryBalanceDetails();
                        details.setFactoryId(attach);
                        details.setFactoryMoney(totalFee);
                        details.setFactoryClassify("1");
                        details.setFactoryType("3");
                        details.setFactoryOrderNum(outTradeNo);
                        details.setFactoryTransactionId(transactionId);
                        details.setFactoryBalance(factory.getFactoryMoney());
                        zsyhFactoryBalanceDetailsService.insertZsyhFactoryBalanceDetails(details);

                    }else{
                        //合同约定保证金金额 减去 保证金余额 小于 本次充值金额   例如 合同约定500，余额400 差100，本次充值200，那么100给保证金余额，100给补助金余额
                        //本次充值金额，分开添加到保证，和补助金余额
                        BigDecimal balanceAdd = totalFee.subtract(contractAmount);//本次充值金额 减去 （合同约定保证金金额 减去 保证金余额）

                        factory = new ZsyhPlatformFactory();
                        factory.setId(attach);
                        factory.setFactoryBalance(balance.add(balanceAdd).setScale(2, BigDecimal.ROUND_HALF_UP));
                        factory.setFactoryMoney(money.add(contractAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
                        zsyhPlatformFactoryService.updateZsyhPlatformFactory(factory);


                        ZsyhFactoryBalanceDetails details = new ZsyhFactoryBalanceDetails();
                        details.setFactoryId(attach);
                        details.setFactoryMoney(contractAmount.setScale(2, BigDecimal.ROUND_HALF_UP));
                        details.setFactoryClassify("1");
                        details.setFactoryType("3");
                        details.setFactoryOrderNum(outTradeNo);
                        details.setFactoryTransactionId(transactionId);
                        details.setFactoryBalance(factory.getFactoryMoney());
                        zsyhFactoryBalanceDetailsService.insertZsyhFactoryBalanceDetails(details);

                        ZsyhFactoryBalanceDetails details1 = new ZsyhFactoryBalanceDetails();
                        details1.setFactoryId(attach);
                        details1.setFactoryMoney(balanceAdd.setScale(2, BigDecimal.ROUND_HALF_UP));
                        details1.setFactoryClassify("2");
                        details1.setFactoryType("1");
                        details1.setFactoryOrderNum(outTradeNo);
                        details1.setFactoryTransactionId(transactionId);
                        details1.setFactoryBalance(factory.getFactoryBalance());
                        zsyhFactoryBalanceDetailsService.insertZsyhFactoryBalanceDetails(details1);


                    }

                }



                result.put("return_code", "SUCCESS");
                result.put("return_msg", "支付成功");
                logger.info("4.订单：" + outTradeNo + " 交易完成" + ">>>" + transactionId);
            } else {
                result.put("return_code", "FAIL");
                result.put("return_msg", "签名失败");
                logger.error("签名验证失败>>>>>>>>>>>>");
            }
        } else {
            result.put("return_code", "FAIL");
            result.put("return_msg", "支付失败");
            logger.error("");
        }


        returnxml = WXPayUtil.mapToXml(result);
        return returnxml;
    }

    /**
     * 厂家充值 充值回调
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/notifyUrlAfterFactoryRecharge", method = RequestMethod.POST)
    @ResponseBody
    public String notifyUrlAfterFactoryRecharge(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        WXPayRequest wxPayRequest = new WXPayRequest(this.wxPayConfig);
        Map<String, String> result = new HashMap<String, String>();
        Map<String, String> params = null;
        String returnxml = "";
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        //以字节流的形式读取request中的数据
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        params = WXPayUtil.xmlToMap(sb.toString());
        logger.info("1.notify-params>>>>>>>>>>>:" + params);

        String returnCode = params.get("return_code");
        logger.info("3.returnCode:" + returnCode);
        if (returnCode.equals("SUCCESS")) {
            //判断签名是否正确
            boolean flag = wxPayRequest.isResponseSignatureValid(params, partnerKey);
            logger.info("2.notify-flag:" + flag);
            if (flag) {
                //获取微信订单号
                String transactionId = params.get("transaction_id");
                //获取商户订单号
                String outTradeNo = params.get("out_trade_no");

                String total_fee = params.get("total_fee");//支付金额

                //附加信息原路返回 厂家id
                String attach = params.get("attach");
                logger.info("transactionId====================================" + transactionId);
                logger.info("outTradeNo====================================" + outTradeNo);
                logger.info("attach====================================" + attach);
                logger.info("total_fee====================================" + total_fee);
                logger.info("outTradeNo====================================" + outTradeNo);
                //TODO 充值成功，保存余额明细，增加余额

                Double total = Double.valueOf(total_fee) * 0.01;
                BigDecimal totalFee = new BigDecimal(String.valueOf(total));

                ZsyhAfterFactoryBalance factoryBalance = zsyhAfterFactoryBalanceService.selectZsyhAfterFactoryBalanceByBalanceRechargeState(outTradeNo);

                ZsyhAfterFactoryBalance factoryBalance1 = new ZsyhAfterFactoryBalance();
                factoryBalance1.setId(factoryBalance.getId());


                String balanceClassify = factoryBalance.getBalanceClassify();//分类 1保证金明细 2余额明细
                String factoryId = factoryBalance.getFactoryId();
                ZsyhAfterFactory factory = zsyhAfterFactoryService.selectZsyhAfterFactoryById(factoryId);
                ZsyhAfterFactory factory1 = new ZsyhAfterFactory();
                factory1.setId(factoryId);

                BigDecimal factoryAll = factory.getFactoryAll();//厂家账户充值总金额
                BigDecimal balance = factory.getFactoryBalance();//厂家账户可用余额
                BigDecimal factoryMoney = factory.getFactoryMoney();//厂家账户保证金
                factoryBalance1.setBalancePayNum(transactionId);
                factoryBalance1.setBalanceRechargeState("1");

                if("1".equals(balanceClassify)){
                    factory1.setFactoryMoney(factoryMoney.add(totalFee).setScale(2, BigDecimal.ROUND_HALF_UP));
                    factoryBalance1.setBalanceMoneyAfter(factory1.getFactoryMoney());
                }else{
                    factory1.setFactoryBalance(balance.add(totalFee).setScale(2, BigDecimal.ROUND_HALF_UP));
                    factory1.setFactoryAll(factoryAll.add(totalFee).setScale(2, BigDecimal.ROUND_HALF_UP));
                    factoryBalance1.setBalanceMoneyAfter(factory1.getFactoryBalance());
                }

                zsyhAfterFactoryBalanceService.updateZsyhAfterFactoryBalance(factoryBalance1);
                zsyhAfterFactoryService.updateZsyhAfterFactory(factory1);


                result.put("return_code", "SUCCESS");
                result.put("return_msg", "支付成功");
                logger.info("4.订单：" + outTradeNo + " 交易完成" + ">>>" + transactionId);
            } else {
                result.put("return_code", "FAIL");
                result.put("return_msg", "签名失败");
                logger.error("签名验证失败>>>>>>>>>>>>");
            }
        } else {
            result.put("return_code", "FAIL");
            result.put("return_msg", "支付失败");
            logger.error("");
        }


        returnxml = WXPayUtil.mapToXml(result);
        return returnxml;
    }


    /**
     * 获取请求预支付id报文
     *
     * @return
     */
    @SuppressWarnings("static-access")
    public String getPackageApplets(WxPayDto tpWxPayDto) {

        String openId = tpWxPayDto.getOpenId();
        // 1 参数
        // 订单号
        String orderId = tpWxPayDto.getOrderId();
        // 附加数据 原样返回
        String attach = tpWxPayDto.getAttach();
        // 总金额以分为单位，不带小数点
        String totalFee = StringUtils.getMoney(tpWxPayDto.getTotalFee());

        // 订单生成的机器 IP
        String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
//        String notify_url = "https://www.zzzsyh.com/cs_pay/wxpay/notify";
        String trade_type = "JSAPI";

        // ---必须参数
        // 商户号
        String mch_id = partner;
        // 随机字符串
        String nonce_str = StringUtils.getNonceStr();

        // 商品描述根据情况修改
        String body = tpWxPayDto.getBody();

        // 商户订单号
        String out_trade_no = orderId;

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appIdApplet);
        packageParams.put("attach", attach);
        packageParams.put("body", body);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);

        packageParams.put("notify_url", notifyUrlFactoryRecharge);
        packageParams.put("openid", openId);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("total_fee", totalFee);
        packageParams.put("trade_type", trade_type);


        RequestHandler reqHandler = new RequestHandler(null, null);
        reqHandler.init(appIdApplet, appSecretApplet, partnerKey);

        String sign = reqHandler.createSign(packageParams);
        logger.info("第一次签名------------------------------" + sign);
        String xml = "<xml>" + "<appid>" + appIdApplet + "</appid>" + "<mch_id>"
                + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
                + "</nonce_str>" + "<sign>" + sign + "</sign>"
                + "<body><![CDATA[" + body + "]]></body>"
                + "<out_trade_no>" + out_trade_no
                + "</out_trade_no>" + "<attach>" + attach + "</attach>"
                + "<total_fee>" + totalFee + "</total_fee>"
                + "<spbill_create_ip>" + spbill_create_ip
                + "</spbill_create_ip>" + "<notify_url>" + notifyUrlFactoryRecharge
                + "</notify_url>" + "<trade_type>" + trade_type
                + "</trade_type>" + "<openid>" + openId + "</openid>"
                + "</xml>";
        String prepay_id = "";
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";


        prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);

        logger.info("获取到的预支付ID：" + prepay_id);


        //获取prepay_id后，拼接最后请求支付所需要的package

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        String packages = "prepay_id=" + prepay_id;
        finalpackage.put("appId", appIdApplet);
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", nonce_str);
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");
        //要签名
        String finalsign = reqHandler.createSign(finalpackage);
        logger.info("第二次签名------------------------------" + finalsign);
        String finaPackage = "\"appId\":\"" + appIdApplet + "\",\"timeStamp\":\"" + timestamp
                + "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\""
                + packages + "\",\"signType\" : \"MD5" + "\",\"paySign\":\""
                + finalsign + "\"";

        logger.info("V3 jsApi package:" + finaPackage);
        return finaPackage;
    }
}
